import hashlib
import os
import winreg


lisenceInfo = [None, None]
key_path = r"SOFTWARE\FSZONE\UNIZVedioManager"
value_name = "FSZONE"


def get_first_disk_serial_windows() -> str:
    try:
        # 使用 wmic 命令获取磁盘序列号
        result = os.popen("wmic diskdrive get SerialNumber").read()
        # 分割结果，去掉标题行和空行
        lines = result.split("\n")
        for line in lines:
            if line.strip() and "SerialNumber" not in line:
                # 返回第一个非空的磁盘序列号
                return line.strip()
    except Exception as e:
        # print(f"获取磁盘序列号时出错: {e}")
        return None


def get_first_baseboard_serial_windows() -> str:
    try:
        # 使用 wmic 命令获取磁盘序列号
        result = os.popen("wmic baseboard get SerialNumber").read()
        # 分割结果，去掉标题行和空行
        lines = result.split("\n")
        for line in lines:
            if line.strip() and "SerialNumber" not in line:
                # 返回第一个非空的磁盘序列号
                return line.strip()
    except Exception as e:
        # print(f"获取磁盘序列号时出错: {e}")
        return None


def get_first_cpu_serial_windows() -> str:
    try:
        # 使用 wmic 命令获取磁盘序列号
        result = os.popen("wmic cpu get ProcessorId").read()
        # 分割结果，去掉标题行和空行
        lines = result.split("\n")
        for line in lines:
            if line.strip() and "ProcessorId" not in line:
                # 返回第一个非空的磁盘序列号
                return line.strip()
    except Exception as e:
        # print(f"获取磁盘序列号时出错: {e}")
        return None


def split_string_to_list(input_string):
    # 输入字符串的长度必须是8的倍数
    if len(input_string) % 8 != 0:
        raise ValueError("输入字符串的长度必须是8的倍数")

    # 用列表推导式按8个字符一组拆分字符串
    split_list = [input_string[i:i + 8] for i in range(0, len(input_string), 8)]
    return split_list


def calc_cid() -> str:
    # 计算CID
    disk = get_first_disk_serial_windows()
    baseboard = get_first_baseboard_serial_windows()
    cpu = get_first_cpu_serial_windows()
    if disk == None or baseboard == None or cpu == None:
        return None
    else:
        empobj = disk + 'FS ZONE' + baseboard + 'FS ZONE' + cpu
        md5_hash = hashlib.md5()
        md5_hash.update(empobj.encode('UTF-8'))
        md5_value = md5_hash.hexdigest()
        empobjList = split_string_to_list(md5_value)
        cid = empobjList[0][0] + empobjList[1][0] + empobjList[0][7] + empobjList[1][7] + '-' + \
            empobjList[2][0] + empobjList[3][0] + empobjList[2][7] + empobjList[3][7]
        cid = cid.upper()
        return cid


def calc_license(uid):
    # 还原操作
    md5id = uid[5] + uid[7] + '-' + uid[0] + uid[2] + '-' + uid[1] + uid[3] + '-' + uid[6] + uid[8]
    # 创建一个 SHA-1 哈希对象
    sha1 = hashlib.sha1()
    # 更新哈希对象，对输入字符串进行编码
    sha1.update(md5id.encode('utf-8'))
    # 返回哈希值的十六进制表示
    sha1List = split_string_to_list(sha1.hexdigest())

    # 创建一个 SHA-1 哈希对象
    md5 = hashlib.md5()
    # 更新哈希对象，对输入字符串进行编码
    md5.update(md5id.encode('utf-8'))
    # 返回哈希值的十六进制表示
    md5List = split_string_to_list(md5.hexdigest())

    lc = sha1List[0] + '-' + md5List[0] + '-' + sha1List[1] + '-' + md5List[1] + '-' + sha1List[2] + '-' + md5List[2] + \
        '-' + sha1List[3] + '-' + md5List[3] + '-' + sha1List[4]
    return lc


def read_from_registry(key_path, value_name):
    # 从注册表读取证书
    # # 示例使用
    # key_path = r"Software\MyApp\Certificates"  # 请根据实际需要修改
    # value_name = "MyCertificate"
    #
    # certificate_content = read_from_registry(key_path, value_name)
    try:
        # 打开注册表键
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path, 0, winreg.KEY_READ)

        # 读取值
        value_data, value_type = winreg.QueryValueEx(key, value_name)

        # 关闭注册表键
        winreg.CloseKey(key)

        # print(f"从注册表读取的数据: {value_data}")
        return [value_data, value_type]
    except FileNotFoundError:
        # print("指定的注册表路径或值不存在。")
        return [-1, -1]
    except Exception as e:
        # print(f"读取注册表时出错: {e}")
        return [None, None]


def create_registry_key():
    try:
        # 打开 HKEY_LOCAL_MACHINE 下的 SOFTWARE 键
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE", 0, winreg.KEY_WRITE)
        # 创建 FSZONE 键，如果不存在则创建
        fszone_key = winreg.CreateKey(key, "FSZONE")
        # 在 FSZONE 键下创建 UNIZVedioManager 键
        unizvedio_key = winreg.CreateKey(fszone_key, "UNIZVedioManager")
        # 关闭键句柄
        winreg.CloseKey(unizvedio_key)
        winreg.CloseKey(fszone_key)
        winreg.CloseKey(key)

        # print("Registry keys created successfully.")
        return 0
    except Exception as e:
        # print(f"An error occurred: {e}")
        return -1


def write_to_registry(key_path, value_name, value_data):
    # 把证书写入注册表
    # # 示例使用
    # key_path = r"Software\MyApp\Certificates"  # 请根据实际需要修改
    # value_name = "MyCertificate"
    # certificate_content = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
    #
    # write_to_registry(key_path, value_name, certificate_content)
    try:
        create_registry_key()
        # 打开注册表键
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path, 0, winreg.KEY_SET_VALUE)

        # 将值写入注册表
        winreg.SetValueEx(key, value_name, 0, winreg.REG_SZ, value_data)

        # 关闭注册表键
        winreg.CloseKey(key)

        # print(f"成功将数据写入注册表: {key_path}\\{value_name}")
        return 0
    except Exception as e:
        # print(f"写入注册表时出错: {e}")
        return -1


def loadLisenceInfo():
    global lisenceInfo
    lisenceInfo[0] = calc_cid()
    lisenceInfo[1] = read_from_registry(key_path, value_name)


def getActStatus():
    """获取软件激活状态"""
    global lisenceInfo
    if lisenceInfo[1][1] == None:
        # 注册表异常
        return False
    elif lisenceInfo[1][1] == 1:
        lcstr = calc_license(lisenceInfo[0])
        if lisenceInfo[1][0] == lcstr:
            return True
        else:
            # 激活码不匹配，请检查或联系客服
            return False
    else:
        return False


def runAct(cid, cervalue):
    """
    执行激活操作
    :param cid:
    :param cervalue:
    :return:
    """
    if len(cervalue) == 80:
        lcstr = calc_license(cid)
        if cervalue == lcstr:
            if write_to_registry(key_path, value_name, cervalue) == -1:
                # 异常
                # self.show_message('激活信息写入异常，程序即将关闭，请用管理员权限运行软件后重新激活！')
                return -3
            else:
                # 激活成功，请重启软件生效
                return 0
        else:
            # self.actvalue_LineEdit.setText('激活码不匹配')
            # self.show_message('激活码不匹配！')
            return -2
    else:
        # self.actvalue_LineEdit.setText('激活码内容无效')
        # self.show_message('激活码内容无效！')
        return -1


def getActCode() -> str:
    global lisenceInfo
    if getActStatus():
        return lisenceInfo[1][0]
    else:
        return ""


def getLisenceInfo_CID():
    global lisenceInfo
    return lisenceInfo[0]

